﻿using System;

namespace Microsoft.Popfly.GameCreator.GameEngine.Behaviors
{
    public class SimpleXMaxSpeedMove : XMoveBehavior
    {
        public SimpleXMaxSpeedMove(BehaviorOwner owner, double maxSpeed) : base(owner, maxSpeed){}


        #region Behavior Members

        public override void Invoke(BehaviorOwner sender, Events.PGCEventArgs args)
        {
            m_owner.XAcceleration += MoveHelpers.CalculateAccelerationFromMaxSpeed(m_offset, m_owner.XDrag);
        }

        #endregion
    }

    public class SimpleYMaxSpeedMove : YMoveBehavior
    {
        public SimpleYMaxSpeedMove(BehaviorOwner owner, double maxSpeed) : base(owner, maxSpeed) {}


        #region Behavior Members

        public override void Invoke(BehaviorOwner sender, Events.PGCEventArgs args)
        {
            m_owner.YAcceleration += MoveHelpers.CalculateAccelerationFromMaxSpeed(m_offset, m_owner.YDrag);
        }

        #endregion
    }

    public class SimpleXYMaxSpeedMove : XYMoveBehavior
    {
        private double m_XMaxSpeed;
        private double m_YMaxSpeed;

        private static double sqrtOfTwoOverTwo = Math.Sqrt(2) / 2.0;

        public SimpleXYMaxSpeedMove(BehaviorOwner owner, double maxSpeedMagnitude, Data.MotionInfo.DirectionValues direction) : base (owner, maxSpeedMagnitude)
        {
            switch (direction)
            {
                case Data.MotionInfo.DirectionValues.NE:
                    m_XMaxSpeed = sqrtOfTwoOverTwo;
                    m_YMaxSpeed = -sqrtOfTwoOverTwo;
                    break;
                case Data.MotionInfo.DirectionValues.NW:
                    m_XMaxSpeed = -sqrtOfTwoOverTwo;
                    m_YMaxSpeed = -sqrtOfTwoOverTwo;
                    break;
                case Data.MotionInfo.DirectionValues.SE:
                    m_XMaxSpeed = sqrtOfTwoOverTwo;
                    m_YMaxSpeed = sqrtOfTwoOverTwo;
                    break;
                case Data.MotionInfo.DirectionValues.SW:
                    m_XMaxSpeed = -sqrtOfTwoOverTwo;
                    m_YMaxSpeed = sqrtOfTwoOverTwo;
                    break;
                default:
                    throw new ArgumentException(
                        Utils.ErrorMessagePrefix + "SimpleXYMove is only for direction values of NE, NW, SE or SW.  '" +
                        direction.ToString() + "' was passed in instead.");
            }
            m_XMaxSpeed *= maxSpeedMagnitude;
            m_YMaxSpeed *= maxSpeedMagnitude;
        }

        #region Behavior Members

        public override void Invoke(BehaviorOwner sender, Events.PGCEventArgs args)
        {
            if (m_isOriginalDirection)
            {
                m_owner.YAcceleration += MoveHelpers.CalculateAccelerationFromMaxSpeed(m_YMaxSpeed, m_owner.YDrag);
                m_owner.XAcceleration += MoveHelpers.CalculateAccelerationFromMaxSpeed(m_XMaxSpeed, m_owner.XDrag);
            }
            else
            {
                m_owner.YAcceleration -= MoveHelpers.CalculateAccelerationFromMaxSpeed(m_YMaxSpeed, m_owner.YDrag);
                m_owner.XAcceleration -= MoveHelpers.CalculateAccelerationFromMaxSpeed(m_XMaxSpeed, m_owner.XDrag);
            }
        }

        #endregion
    }

    public class SimpleMaxSpeedRotation : RotateBehavior
    {
        private Actor m_actorOwner;

        public SimpleMaxSpeedRotation(Actor owner, double maxSpeed) : base(owner, maxSpeed)
        {
            m_actorOwner = owner;
            m_offset = maxSpeed;
        }

        public SimpleMaxSpeedRotation(Actor owner, Data.MotionInfo rotationInfo) : base(owner, rotationInfo.MaxSpeed)
        {
            m_actorOwner = owner;

            if (rotationInfo.Relative != Data.MotionInfo.RelativeValues.Self)
            {
                throw new ArgumentException(
                    Utils.ErrorMessagePrefix +
                    "SimpleRotation only knows how to handle clockwise/counterclockwise motions relative to self.  '"
                    + rotationInfo.Relative.ToString() + "' was passed in."
                    );
            }

            switch (rotationInfo.Direction)
            {
                case Data.MotionInfo.DirectionValues.E:
                    m_offset = -m_offset;
                    break;
                case Data.MotionInfo.DirectionValues.W:
                    break;
                default:
                    throw new ArgumentException(
                        Utils.ErrorMessagePrefix +
                        "SimpleRotation only understands E for counter clockwise and W for clockwise.  '" +
                        rotationInfo.Direction.ToString() + "' was passed in."
                        );
            }
        }

        #region Behavior Members

        public override void Invoke(BehaviorOwner sender, Events.PGCEventArgs args)
        {
            m_actorOwner.RotationAcceleration += MoveHelpers.CalculateAccelerationFromMaxSpeed(m_offset, m_actorOwner.RotationDrag);
        }

        #endregion
    }
}
